package com.example.observer;

import com.sun.org.slf4j.internal.Logger;
import com.sun.org.slf4j.internal.LoggerFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;

/**
 监听者的实现，关键在于实现ApplicationListener的onApplicationEvent的接口方法即可。
 又因为未来别的业务场景接入观察者模式，都是按你的模板来，
 所以各个Event事件对象，都是继承于你的BaseEvent的，
 所以我们可以把<T extends BaseEvent>的泛型加进去，如下：
 * @param <T>
 */
public interface EventListener<T extends BaseEvent> extends ApplicationListener<T> {

    @Override
    default void onApplicationEvent(T event){
        try {
            if(this.support(event)){
                this.handleEvent(event);
            }
        }catch (Throwable t){
            this.handleException(t);
        }

    }

    /**
     * 有些时候，可能会有这种场景，就是执行监听逻辑，只对部分数据（或者说部分特殊用户才执行）。
     * 既然我们是抽取监听模板，考虑到可扩展性，我们可以优化下IEventListener的代码。
     * 我们可以声明一个support的方法，默认是执行的,子类可以覆盖重写（让子类去控制是否执行这个监听逻辑），如下：
     * @param event
     * @return
     */
    default boolean support(T event){
        return true;
    }

    /**
     * 只有support方法返回true，
     * 才执行监听的逻辑，我们还可以定义一个handle方法，
     * 给子类去实现自己的业务逻辑，代码如下：
     * @param event
     */
    void handleEvent(T event);

    /**
     * 我们可以给onApplicationEvent的实现try...catch...一下，
     * 如果catch住异常的话，可以定义一个handlerException异常处理方法，
     * 给子类自定义去实现，当然，异常可以默认不处理嘛，代码如下：
     * @param t
     */
    default void handleException(Throwable t){
        // by default, log with error level
        Logger logger = LoggerFactory.getLogger(this.getClass());
        logger.error("default exception handler:",t);
    }
}
